package com.BlackMesa.models;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import com.BlackMesa.database.*;
import com.google.android.maps.GeoPoint;

import android.graphics.Color;
import android.util.Log;

/**
 * Represents the user of the app; keeps track of the user's categories and other information.
 * @author Tyler Bishop
 * @version 1.0
 */


public class User implements Serializable{
	private String name, username, email, password;
	private ArrayList<Category> categories;
	private ArrayList<OurLocation> locations;
	private Category activeCategory,allTasks,incompleteTasks;
	private int id;
	private DatabaseAdapter adapter;
	
	/**
	 * Sets up a user with the given information.
	 * @param name
	 * 		name of the user
	 * @param username
	 * 		alias the user uses to login with
	 * @param email
	 * 		email address for the user
	 * @param password
	 * 		unsecure password the user uses to login with
	 */
	public User(String name, String username, String email, String password) {
		
		this.name = name;
		this.username = username;
		this.email = email;
		this.password = password;
		locations = new ArrayList<OurLocation>();
		categories = new ArrayList<Category>();
		allTasks = new Category("All Tasks", 0);
		allTasks.setTasks(adapter.getAll(this));
		Log.d("blah", "here");
		//adapter.createCategory(allTasks);
		incompleteTasks = new Category("Incomplete", 0);
		categories.add(allTasks);
		categories.add(incompleteTasks);
		activeCategory = allTasks;
	}
	
	
	public User(String name, String username, String email, String password, DatabaseAdapter adapter) {
		this.name = name;
		this.username = username;
		this.email = email;
		this.adapter = adapter;
		this.password = password;
		locations = new ArrayList<OurLocation>();
		locations = adapter.getLocations(id);
		categories = new ArrayList<Category>();
		if (id == 0) {
			this.id = 1;
		}
		categories = adapter.getCategories(id);
		allTasks = categories.get(0);
		//adapter.createCategory(allTasks);
		//adapter.createLocation(new OurLocation("dummy", new GeoPoint(0,0)), this.id);
		incompleteTasks = new Category("Incomplete", 0);
		categories.add(allTasks);
		categories.add(incompleteTasks);
		activeCategory = allTasks;
	}
	
	public User(int id, String name, String username, String email, String password, DatabaseAdapter adapter) {
		this.name = name;
		this.id = id;
		this.username = username;
		this.email = email;
		this.adapter = adapter;
		this.password = password;
		locations = new ArrayList<OurLocation>();
		locations = adapter.getLocations(id);
		categories = new ArrayList<Category>();
		categories = adapter.getCategories(id);
		allTasks = new Category("All Tasks", 0);
		allTasks.setTasks(adapter.getAll(this));
		//adapter.createCategory(allTasks);
		//adapter.createLocation(new OurLocation("dummy", new GeoPoint(0,0)), this.id);
		incompleteTasks = new Category("Incomplete", 0);
		categories.add(allTasks);
//		categories.add(incompleteTasks);
		incompleteTasks = new Category("Incomplete", 0);
		categories.add(allTasks);
		categories.add(incompleteTasks);
		activeCategory = allTasks;
	}
	
	public ArrayList<Task> getIsComplete() {
		return adapter.getIncomplete(this.id);
	}
	
//	public User(int id, String name, String username, String email, String password) {
//		this.id = id;
//		this.name = name;
//		this.username = username;
//		this.email = email;
//		this.password = password;
//		categories = new ArrayList<Category>();
//		locations = new ArrayList<OurLocation>();
//		allTasks = new Category("", 0);
//		incompleteTasks = new Category("Incomplete", 0);
//		categories.add(allTasks);
//		categories.add(incompleteTasks);
//		activeCategory = allTasks;
//	}
	
	/**
	 * Sets up a null user.
	 */
	public User() {
		name = username = email = password = null;
	}
	
	public Category AllTasks() {
		return allTasks;
	}
	
	/**
	 * Checks to see if the given pass word is the one the user has.
	 * @param inputPass
	 * 		password given to the app
	 * @return boolean
	 * 		whether the password is the user's
	 */
	public boolean checkPass(String inputPass) {
		if(password != null) {
			return password.equals(inputPass);
		}
		return false;
	}
	
	/**
	 * Finds the category whose name matches the parameter.
	 * @param cat
	 * 		name of the category
	 * @return Category
	 * 		category whose name is the parameter; null if it is not in the list
	 */
	public Category getCategoryWithString(String cat) {
		for(Category c: categories) {
			if(c.getName().equals(cat)) {
				return c;
			}
		}
		return null;
	}
	
	/**
	 * 
	 * @param cat
	 * @return
	 */
	public boolean containsCategory(String cat) {
		return containsCategory(new Category(cat,0));
	}
	
	/**
	 * 
	 * @param cat
	 * @return
	 */
	public boolean containsCategory(Category cat) {
		for(Category c : categories) {
			if (c == null) {
				return false;
			}
			if(c.equals(cat)) {
				return true;
			}
		}
		return false;
	}
	
	/**
	 * Calls the addTask method with the category whose name matches the cat param
	 * @param cat
	 * 		name of the category the task is being added to
	 * @param task
	 * 		task being added to the list
	 */
	public void addTask(String cat,Task task) {
		if(getCategoryWithString(cat) == null) {
			addTask(new Category(cat,0),task);
		} else {
			addTask(getCategoryWithString(cat),task);
		}
	}
	/**
	 * Adds the task to the given category unless cat is null; always adds the task to allTasks.
	 * @param cat
	 * 		category the task is added to, if any
	 * @param task
	 * 		task being added
	 */
	public void addTask(Category cat, Task task) {
		task.setUserid(this.id);
		task.setCategory(cat);
		adapter.createTask(task);
		allTasks.addTask(task,true);
		incompleteTasks.addTask(task,true);
		if(!cat.equals(allTasks)) {
			if(!containsCategory(cat)) {
				categories.add(cat);
				//adapter.createCategory(cat);
			}
			cat.addTask(task,false);
		}
	}
	/**
	 * 
	 * @param task
	 */
	public void addTask(Task task) {
		addTask(activeCategory,task);
	}


	public Category AllTask() {
		
		return allTasks;
	}
	public Category IncompleteTasks() {
		return incompleteTasks;
	}
	/**
	 * Creates a new category with the given name and color; if task is not 
	 * null that task is added to the newly created category.
	 * @param name
	 * @param color
	 * @param task
	 */
	public Category createCategory(String name, int color, Task task) {
		Category cat = null;
		if(!containsCategory(name)) {
			cat = new Category(name, color);
			cat.setUserid(this.id);
			cat.setId(adapter.createCategory(cat));
			//adapter.createCategory(cat);
		} else if(name == "") {
			cat = allTasks;
		} else {
			cat = getCategoryWithString(name);
		}
		if(task != null) {
			addTask(cat,task);
		}
		return cat;
	}
	
	
	/**
	 * Creates a new category with the given name and color; if task is not 
	 * null that task is added to the newly created category.
	 * @param name
	 * @param color
	 * @param task
	 */
	public Category createCategory(String name, Color color, Task task, DatabaseAdapter adapter) {
		Category cat = null;
		if(!containsCategory(name)) {
			cat = new Category(name, 0);
			cat.setUserid(this.id);
			adapter.createCategory(cat);
			
		} else {
			cat = getCategoryWithString(name);
		}
		if(task != null) {
			addTask(cat,task);
		}
		return cat;
	}
	
	public void addCategory(Category cat) {
		if(cat == null) {
			return;
		}
		if(!categories.contains(cat)) {
			categories.add(cat);
		}
	}
	
	/**
	 * Calls the deleteCategory method with the category whose name matches the name param.
	 * @param name
	 * 		name of the category to be deleted
	 * @param willDeleteTasks
	 * 		determines if the tasks are going to be deleted as well
	 */
	public void deleteCategory(String name, boolean willDeleteTasks, DatabaseAdapter adapter) {
		deleteCategory(getCategoryWithString(name),willDeleteTasks);
		adapter.deleteCategory(getCategoryWithString(name).getId());
	}
	/**
	 * Deletes the given category; also has a check for deleting all tasks associated with that category or not. 
	 * @param cat
	 * 		category being deleted
	 * @param willDeleteTasks
	 * 		whether the tasks associated with that category are deleted as well
	 */
	public void deleteCategory(Category cat, boolean willDeleteTasks) {
		if(cat != null) {
			if(willDeleteTasks) {
				for(Task t:cat.getTasks()) {
					allTasks.removeTask(t);
					incompleteTasks.removeTask(t);
				}
			} else {
				for(Task t:cat.getTasks()) {
					t.setCategory(allTasks);
					t.setCategory(incompleteTasks);
				}
			}
			categories.remove(cat);
		}
	}
	
	/**
	 * Deletes the given task from the list.
	 * @param task
	 * 		task to be deleted
	 */
	public void deleteTask(Task task) {
		if(task.getCategory() != null) {
			task.getCategory().removeTask(task);
		}
		allTasks.removeTask(task);
		incompleteTasks.removeTask(task);
	}
	
	
	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getUsername() {
		return username;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getPassword() {
		return password;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getEmail() {
		return email;
	}

	public ArrayList<Category> getCategories() {
		return categories;
	}

	public void setCategories(ArrayList<Category> categories) {
		this.categories = categories;
	}

	public Category getActiveCategory() {
		return activeCategory;
	}

	/**
	 * 
	 * @param activeCategory
	 */
	public void setActiveCategory(Category activeCategory) {
		this.activeCategory = activeCategory;
	}
	
	/**
	 * 
	 * @param aCat
	 */
	public void setActiveCategoryWithString(String aCat) {
		activeCategory = (getCategoryWithString(aCat)!=null) ? getCategoryWithString(aCat) : (aCat.equals("Incomplete"))?getIncomplete():allTasks;
	}
	
	public Category getIncomplete() {
		Category cat = new Category("Incomplete",0);
		ArrayList<Task> incom = new ArrayList<Task>();
		for(Task t:AllTasks().getTasks()) {
			if(!t.isComplete()) {
				incom.add(t);
			}
		}
		cat.setTasks(incom);
		return cat;
	}
	
	/**
	 * 
	 * @param t
	 */
	public void switchTaskComplete(Task t) {
		t.switchComplete();
		adapter.switchComplete(t);
	}

	/**
	 * 
	 * @param dateTime
	 */
	public void tasksAfterDate(Date dateTime) {
		activeCategory = new Category("",0);
		for(Task t:allTasks.getTasks()) {
			if (t.getDueDate() == null) {
				continue;
			}
			if(t.getDueDate().after(dateTime)){
				activeCategory.addTaskForDate(t);
			}
		}
	}
	
	public OurLocation getLocationWithName(String name) {
		OurLocation newLoc = null;
		for(OurLocation loc:locations) {
			if(name.equals(loc.getName())) {
				newLoc = loc;
				break;
			}
		}
		return newLoc;
	}

	/**
	 * @return the id
	 */
	public int getId() {
		return id;
	}

	/**
	 * @param id the id to set
	 */
	public void setId(int id) {
		this.id = id;
	}
	

	public ArrayList<OurLocation> getLocations() {
		return locations;
	}

	public void setLocations(ArrayList<OurLocation> locations) {
		this.locations = locations;
	}

	public DatabaseAdapter getAdapter() {
		return adapter;
	}

	public void setAdapter(DatabaseAdapter adapter) {
		this.adapter = adapter;
	}
	
}
